---
keywords:
- state
- access
- storage
- key
- data
- value
description: The smart contract state storage on the host consists of a single key/value map, as long as you access the data in the same way that you used to store it, you will always get valid data back.
image: /img/logo/WASP_logo_dark.png
---
import Tabs from "@theme/Tabs"
import TabItem from "@theme/TabItem"

# Smart Contract State

The smart contract state storage on the host consists of a single key/value map. Both key
and value are raw data bytes. As long as you access the data in the same way that you used
to store it, you will always get valid data back. The schema tool will create a type-safe
access layer to make sure that data storage and retrieval always uses the expected data
type.

The `state` section in the schema definition file contains a number of field definitions
that together define the variables that are stored in the state storage. Each field
definition uses a JSON key/value pair to define the name and data type of the field.
The JSON key defines the field name. The JSON value (a string) defines the field's data
type, and can be followed by an optional comment that describes the field.

The schema tool will use this information to generate the specific code that accesses the
state variables in a type-safe way. Let's examine the `state` section of the `dividend`
example in more detail:

<Tabs defaultValue="yaml"
    values={[
        {label: 'schema.yaml', value: 'yaml'},
        {label: 'schema.json', value: 'json'},
    ]}>

<TabItem value="json">

```json
{
  "state": {
    "memberList": "Address[] // array with all the recipients of this dividend",
    "members": "map[Address]Int64 // map with all the recipient factors of this dividend",
    "owner": "AgentID // owner of contract, the only one who can call 'member' func",
    "totalFactor": "Int64 // sum of all recipient factors"
  }
}
```

</TabItem>

<TabItem value="yaml">

```yaml
state:
  memberList: Address[] // array with all the recipients of this dividend
  members: map[Address]Int64 // map with all the recipient factors of this dividend
  owner: AgentID // owner of contract, the only one who can call 'member' func
  totalFactor: Int64 // sum of all recipient factors
```

</TabItem>
</Tabs>

Let's start with the simplest state variables. `totalFactor` is an Int64, and `owner` is
an AgentID. Both are predefined [WasmLib value types](../wasm_vm/types.mdx).

Then you have the `memberList` variable. The empty brackets `[]` indicate that this is an
array. The brackets immediately follow the homogenous type of the elements in the array,
which in this case is the predefined Address value type.

Finally, you have the `members` variable. The `map[]` indicate that this is a map. Between
the brackets is the homogenous type of the keys, which in this case are of the predefined
Address type. The brackets are immediately followed by the homogenous type of the values
in the map, which in this case are of the predefined Int64 type.

Here is part of the code in `state.xx` that the schema tool has generated. The
MutableDividendState struct defines a type-safe interface to access each of the state
variables through mutable proxies:

<Tabs defaultValue="go"
      groupId="language"
      values={[
          {label: 'Go', value: 'go'},
          {label: 'Rust', value: 'rust'},
          {label: 'TypeScript', value: 'ts'},
      ]}>

<TabItem value="go">

```go
type MutableDividendState struct {
    id int32
}

func (s MutableDividendState) MemberList() ArrayOfMutableAddress {
    arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS)
    return ArrayOfMutableAddress{objID: arrID}
}

func (s MutableDividendState) Members() MapAddressToMutableInt64 {
    mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMembers], wasmlib.TYPE_MAP)
    return MapAddressToMutableInt64{objID: mapID}
}

func (s MutableDividendState) Owner() wasmlib.ScMutableAgentID {
    return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxStateOwner])
}

func (s MutableDividendState) TotalFactor() wasmlib.ScMutableInt64 {
    return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateTotalFactor])
}
```

</TabItem>
<TabItem value="rust">

```rust
#[derive(Clone, Copy)]
pub struct MutableDividendState {
    pub(crate) id: i32,
}

impl MutableDividendState {
    pub fn member_list(&self) -> ArrayOfMutableAddress {
        let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), TYPE_ARRAY | TYPE_ADDRESS);
        ArrayOfMutableAddress { obj_id: arr_id }
    }

    pub fn members(&self) -> MapAddressToMutableInt64 {
        let map_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBERS), TYPE_MAP);
        MapAddressToMutableInt64 { obj_id: map_id }
    }

    pub fn owner(&self) -> ScMutableAgentID {
        ScMutableAgentID::new(self.id, idx_map(IDX_STATE_OWNER))
    }

    pub fn total_factor(&self) -> ScMutableInt64 {
        ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR))
    }
}
```

</TabItem>
<TabItem value="ts">

```ts
export class MutableDividendState extends wasmlib.ScMapID {

    memberList(): sc.ArrayOfMutableAddress {
        let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS);
        return new sc.ArrayOfMutableAddress(arrID)
    }

        members(): sc.MapAddressToMutableInt64 {
        let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMembers], wasmlib.TYPE_MAP);
        return new sc.MapAddressToMutableInt64(mapID);
    }

        owner(): wasmlib.ScMutableAgentID {
        return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxStateOwner]);
    }

        totalFactor(): wasmlib.ScMutableInt64 {
        return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]);
    }
}
```

</TabItem>
</Tabs>

As you can see, the schema tool has generated a proxy interface for the mutable `dividend`
state, called `MutableDividendState`. It has a 1-to-1 correspondence to the `state`
section in the schema definition file. Each member function accesses a type-safe proxy
object for the corresponding variable. In addition, the schema tool generates any
necessary intermediate map and array proxy types that force the usage of their respective
homogenous types. In the above example both `ArrayOfMutableAddress` and
`MapAddressToMutableInt64` are examples of such automatically generated proxy types.
See the full `state.xx` for more details.

In the next section we will explore how the schema tool helps to simplify [triggering
events](events.mdx).